
package com.lzx.iteam.util;

import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.util.Xml;
import com.lzx.iteam.R;
import org.xmlpull.v1.XmlPullParser;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;

/**
* SettingsParser class
*
* Parse and hold default settings from xml file resource
* and from customization provider.
* Used by Configuration class.
*
* This class needs to be redesigned together with Configuration, to avoid
* having loadSettings(Context) work differently depending on flags.
*/
public class SettingsParser {
    private static final String TAG = "SettingsParser";

    // STRING CONSTANTS USED FOR XML PARSING.
    // xml tags
    private static final String TAG_SETTINGS = "settings";
    private static final String TAG_SETTING = "setting";
    // xml attr
    private static final String ATTR_KEY = "key";
    //private static final String ATTR_VERSION = "version";
    //private static final String ATTR_RUNTIME = "runtime";

    // phonebook specific settings keys. Used for both xml file key and internal keymap.
    public static final String KEY_BRAND_STRING = "brand";
    public static final String KEY_FACEBOOK = "facebook";
    public static final String KEY_TWITTER = "twitter";
    public static final String KEY_SD_CONTACTS_PATH = "contacts";
    public static final String KEY_DISABLE_INTEGRATED_APP_PRESENCE = "disable-integrated-app-presence";
    // added to sort the account
    public static final String KEY_ACCOUNT_TYPES = "account-types";
    // customization key for hide SIM contacts. (true/false)
    public static final String KEY_HIDE_SIM_CONTACTS = "hide_sim_contacts";

    // ImportGuide specific settings keys.
    public static final String KEY_IMPORTGUIDE_URL = "contacts-tutorial-url";

    // Im services removal setting key
    public static final String KEY_DISABLED_IM_SERVICES = "disabled-im-services";

    // contact fields removal setting key
    public static final String KEY_DISABLED_CONTACT_FIELDS = "disabled-contact-fields";

    // voicebox removal setting key
    public static final String KEY_DISABLED_VOICEMAIL = "disabled-voicemail";

    // speed dialing setting key
    public static final String KEY_ENABLE_SPEED_DIAL = "enable-speed-dial";

    // contacts sort order setting key
    public static final String KEY_DISABLE_SORT_ORDER = "disabled-sort-order";

    // contacts display order setting key
    public static final String KEY_DISABLE_DISPLAY_ORDER = "disabled-display-order";

    // ### proper uri.
    // phonebook customization settings uri.
    private static final String CUSTOMIZATION_SETTINGS_URI = "content://com.sonyericsson.provider.customization/settings/com.sonyericsson.android.socialphonebook";

    private InputStream customizationXmlInputStream = null;
    private boolean disableCustomizationProvider = false;  // only used for testing!

    private final HashMap<String, Boolean> mBooleanDefaultSettings = new HashMap<String, Boolean>();
    private final HashMap<String, String> mStringDefaultSettings = new HashMap<String, String>();

    private final HashSet<String> mDisabledContactFields = new HashSet<String>();

    public void parseSettings(XmlPullParser xpp) throws Exception {
        if (xpp != null) {

            int eventType = xpp.getEventType();
            String tag = null;
            String settingKey = null;
            //String runtime = null;

            while (eventType != XmlPullParser.END_DOCUMENT) {
                if (eventType == XmlPullParser.START_TAG) {
                    tag = xpp.getName();
                    if (tag.equalsIgnoreCase(TAG_SETTINGS)) {
                        //do nothing.
                    } else if (tag.equalsIgnoreCase(TAG_SETTING)) {
                        settingKey = xpp.getAttributeValue(null, ATTR_KEY);

                        if(settingKey == null) {
                            throw new IllegalArgumentException();
                        }

                        eventType = xpp.next(); //normally you got the text.
                        //LogSystem.d(TAG, "    parseSettings eventType=" + eventType);
                        String value = null;
                        if(eventType == XmlPullParser.TEXT) {
                            value = xpp.getText();

                            if(value == null) {
                                throw new IllegalArgumentException();
                            }

                        } else if(eventType == XmlPullParser.END_TAG){
                            // text is Nothing.
                            // set empty string to value.
                            value = "";
                        } else {
                            //ERROR missing end tag.
                            throw new IllegalArgumentException();
                        }

                        try {
                            readDefaultSetting(settingKey, value);
                        } catch (IllegalArgumentException iae) {
                            throw new IllegalArgumentException(iae);
                        }
                    }
                }
                eventType = xpp.next();
            }
        }
    }

    private void readDefaultSetting(String key, String value) throws IllegalArgumentException {

        //find the settings key.
        if (key.equalsIgnoreCase(KEY_BRAND_STRING)) {
            putString(KEY_BRAND_STRING, value);
        } else if (key.equalsIgnoreCase(KEY_FACEBOOK)) {
            putBoolean(KEY_FACEBOOK, value);
        } else if (key.equalsIgnoreCase(KEY_TWITTER)) {
            putBoolean(KEY_TWITTER, value);
        } else if(key.equalsIgnoreCase(KEY_SD_CONTACTS_PATH)) {
            putString(KEY_SD_CONTACTS_PATH, value);
        } else if(key.equalsIgnoreCase(KEY_DISABLE_INTEGRATED_APP_PRESENCE)) {
            putBoolean(KEY_DISABLE_INTEGRATED_APP_PRESENCE, value);
        //sort order for accounts
        } else if(key.equalsIgnoreCase(KEY_ACCOUNT_TYPES)) {
            putString(KEY_ACCOUNT_TYPES, value);
        }else if(key.equalsIgnoreCase(KEY_IMPORTGUIDE_URL)) {
            putString(KEY_IMPORTGUIDE_URL, value);
        } else if (key.equalsIgnoreCase(KEY_DISABLED_IM_SERVICES)) {
            // removal of support for im services
            putString(KEY_DISABLED_IM_SERVICES, value);
        } else if (key.equalsIgnoreCase(KEY_DISABLED_CONTACT_FIELDS)) {
            loadDisabledContactFields(value);
        } else if (key.equalsIgnoreCase(KEY_HIDE_SIM_CONTACTS)) {
            putBoolean(KEY_HIDE_SIM_CONTACTS, value);
        } else if (key.equalsIgnoreCase(KEY_DISABLED_VOICEMAIL)) {
            putBoolean(KEY_DISABLED_VOICEMAIL, value);
        } else if (key.equalsIgnoreCase(KEY_ENABLE_SPEED_DIAL)) {
            putBoolean(KEY_ENABLE_SPEED_DIAL, value);
        } else if (key.equalsIgnoreCase(KEY_DISABLE_SORT_ORDER)) {
            putBoolean(KEY_DISABLE_SORT_ORDER, value);
        } else if (key.equalsIgnoreCase(KEY_DISABLE_DISPLAY_ORDER)) {
            putBoolean(KEY_DISABLE_DISPLAY_ORDER, value);
        } else {
        }

    }

    private void putString(String key, String value) {
        if(mStringDefaultSettings.containsKey(key)) {
        }
        mStringDefaultSettings.put(key, value);
    }

    private void putBoolean(String key, String value) {
        if(mBooleanDefaultSettings.containsKey(key)) {
        }

        boolean bool = false;
        if (value.equalsIgnoreCase("true")) {
            bool = true;
        } else if (value.equalsIgnoreCase("false")) {
            bool = false;
        } else {
            throw new IllegalArgumentException();
        }

        mBooleanDefaultSettings.put(key, bool);
    }

    public String getString(String key) {
        String retValue = null;
        if(!mStringDefaultSettings.containsKey(key)) {
        } else {
            retValue = mStringDefaultSettings.get(key);
        }

        return retValue;
    }

    public boolean getBoolean(String key, boolean def) {
        boolean retValue = def;
        if(!mBooleanDefaultSettings.containsKey(key)) {
        } else {
            retValue = mBooleanDefaultSettings.get(key);
        }

        return retValue;
    }

    /**
     * Loads the settings from default settings xml file and
     * Customization Provider.
     *
     * @param ctx  context have the xml resource.
     * @return<ul>
     * <li>false, if the defaults in res/xml/default_settings.xml could not
     * be parsed.
     * <li>true, if the defaults were parsed ok and setCustomizationProviderDisabled(true)
     * and  setCustomizationXml(null) has been called.
     * <li>true, if the defaults were parsed ok and setCustomizationXml(is) has
     * been called and the customization in is was parsed ok.
     * <li>true if there was an attempt to read the system's customization but
     * the customization file did not exist. I.e.the common case that
     * the customization does not include any special settings for Social
     * Phonebook.
     * <li>false otherwise.
     * </ol>
     */
    public boolean loadSettings(Context ctx) {
        // Handle default and customization settings
        // Parse default settings
        boolean parseDefaultOk = false;

        XmlPullParser xpp = ctx.getResources().getXml(R.xml.default_settings);
        try {
            parseSettings(xpp);
            parseDefaultOk = true;
        } catch (Exception e) {
            e.printStackTrace();
            parseDefaultOk = false;
        }

        // Parse custom settings
        boolean parseCustomOkOrNoCustom = false;

        try {
            if ((!disableCustomizationProvider) && (customizationXmlInputStream == null)) {
                Uri uri = Uri.parse(CUSTOMIZATION_SETTINGS_URI);
                ContentResolver cr = ctx.getContentResolver();
                customizationXmlInputStream = cr.openInputStream(uri);
            }
            if (customizationXmlInputStream != null) {
                XmlPullParser customizedParser = Xml.newPullParser();
                customizedParser.setInput(customizationXmlInputStream, null);
                parseSettings(customizedParser);
            }
            parseCustomOkOrNoCustom = true;
        } catch (FileNotFoundException e) {
            // No customization file exists, not an error
            parseCustomOkOrNoCustom = true;
        } catch (Exception e) {
            parseCustomOkOrNoCustom = false;
            if (disableCustomizationProvider) {
                // Currently Log.e with exception trigger smscrash to be sent, when in
                // "test mode" don't send smscrash.
            } else {
            }
        } finally {
            if (customizationXmlInputStream != null) {
                try {
                    customizationXmlInputStream.close();
                    customizationXmlInputStream = null;
                } catch (IOException e) {
                    //do nothing.
                }
            }
        }

        return (parseDefaultOk && parseCustomOkOrNoCustom);
    }

    /**
     * Change the customization xml, only used for testing
     * @param customizationXmlInputStream, the customization xml to be used
     */
    public void setCustomizationXml(InputStream customizationXmlInputStream) {
        this.customizationXmlInputStream = customizationXmlInputStream;
    }

    /**
     * Disable the default customization URI, only used for testing
     * @param disableCustomizationProvider
     */
    public void setCustomizationProviderDisabled(boolean disableCustomizationProvider) {
        this.disableCustomizationProvider = disableCustomizationProvider;
    }

    /**
     * Reset the state of the parser, only used for testing
     */
    public void reset() {
        this.customizationXmlInputStream = null;
        this.disableCustomizationProvider = false;
    }

    private void loadDisabledContactFields(String disabledContactFields) {
        String[] disabledContactFieldsList = null;

        if (disabledContactFields != null) {
            try {
                disabledContactFieldsList = disabledContactFields.split(",");
            } catch (Exception e) {
            }
        }

        if (disabledContactFieldsList != null && disabledContactFieldsList.length > 0) {
            for (int i = 0; i < disabledContactFieldsList.length; i++) {
                mDisabledContactFields.add(disabledContactFieldsList[i]);
            }
        }
    }

    public boolean isContactFieldDisabled(String mimeType) {
        return mDisabledContactFields.contains(mimeType);
    }

}
